SeminárioLP-Linguagem Python 2/2014 - Carlos Menezes, Daniel Schulz, Maxwell Moura e Lucas
'Introdução' O procedimento do ciclo de produção de software pode ser simplificado em três simples perguntas, a saber: 1) O que eu quero que o software faça? 2) Quem estará usando o software? 3) Em que sistema o usuário o estará executando? No processo de determinar o que o software tem que fazer é recomendado produzir uma whishlist que é conseguida analisando de maneira mias profunda os procedimentos que deverão ser realizados. * Converse com os potenciais usuários do software; * O que eles preferem usar; * Em que formato de arquivo eles querem trabalhar; * O que eles esperam que o software faça. * Assista o usuário realizando à tarefa; * Compile (reuna) histórias do usuário; * Algumas linhas em linguagem comum que especifica o que o usuário quer que o software faça; * A ideia é a de que a história seja pequena o suficiente para cabe em post-its, ou cartões de índices. * Deve deixar claro qual o benefício o usuário receberá em usar o software; * Estas histórias são usadas para criar casos de usuário que são descrições mais detalhadas das especificações do usuário; Derivando uma solução O estágio de projeto pode ser a etapa da “programação” que consome mais tempo. Consiste em várias etapas onde a saída de uma alimenta a entrada de outra. Frequentemente a saída de um ou mais estágios é realimentada através do mesmo processo vária vezes, o que é conhecido como recursão quando ocorre dentro do programa. Os passos a seguir permitem a análise do problema * Entendendo o problema; * Saber o que o software precisa fazer; * As coisas que se quer que o software faça é chamado de requerimentos funcionais; * Ex.: imprimir mensagens, adicionar números, mandar um formulário de e-mail. * Considerar outras necessidades e limitações; * Essas outras considerações são os requerimentos não-funcionais(limitações e qualidades requeridas pelo software); * Ex.: acessibilidade, usabilidade pelo usuário, compatibilidade com outros sistemas, segurança. * Defina os resultados que são aceitáveis; * O que se espera que o programa retorne; * Estabeleça métodos de teste para verificar se o resultado que ser espera é atendido na prática; * É importante automatizar o processo através de suites de teste. * Considere a mantenabilidade; * Toda peça de software que se espera usar mais de uma vez terá que ter algum grau de mantenabilidade; * É bom pensar como o software terá que se portar no futuro e como será possível mantê-lo atualizado; * Para facilitar a manutenção o software deve conter algum meio de contado. Quebrando a solução em passo. Em um programa a quantidade de linhas de comentários é maio que a quantidade de código “real”. Aspas triplas “”” permite criar um bloco de comentário, como /**/ no C. Uma string de texto que ocorre como uma primeira instrução compõem a Python docstring, i.e, a documentação auto construída do python. Organizando as tarefas em passos. Deve separar o projeto em passos ordenados através de pseudo código estabelecendo assim uma abordagem top-down de detalhamento. Esse pseudo código que descreve as tarefas a serem executadas, pode ser escrito no arquivo usado para codificar o programa, desde que cada linha venha precedida pelo símbolo de comentário de linha, #. As sentenças em pseudo código que tiverem uma relação estrita devem vir identadas. A linguagem python considera tanto espaços quanto tabulações identações, apesar de que para o interpretado eles tenham significados diferentes. Toda identação significa alguma coisa, é bom ter isso em mente. Um coisa que deve ser lembrada é de que não se deve misturar espaços e tabulações. * Refina cada linha do pseudo código até alcançar a solução; Codificando o projeto Na criação de uma variável há dois estágios: 1) Inicialização, reserva o conteiner de memória e associal uma label a ele. 2) Faz a atribuição de um valor a esse container. A variável é referencial por um nome, que é o identificador. * Tornando o projeto em um código executável; * Refinamento posterior do projeto; Toda requisição de entrada precisa de uma mensagem informando o usuário que a entrada é requerida. Isso é conhecido como prompt. 'Variáveis' Variável é uma unidade de dado com um identificador que é mantida na memória do computador. Nomes de variáveis podem tanto começar com uma letra ou _. Se o interpretador encontrar um bando de caracteres iniciado por um dígito ele irá considerar tudo um número. Para identificar uma variável não se pode usar nada que letras, números e K _. Python é sensível a maiúscula e minúscula. É recomendável usar um registro pessoal dos nomes de variáveis que já estão em uso. É bom manter uma tabela de variáveis no início de um arquivo de programa. Em python a inicialização (reservar memória e atribuir um label a essa reserva) e a atribuição é realizada em um único comando. Ex.: variable = value. Um seção de código que realiza alguma coisa, como a atribuição é considerada uma instrução (statement). A parte do código que pode ser avaliada para produzir determinado valor é conhecida como expressão. Cada instrução '''deve vir em sua própria linha. Pytohn reconhece vários tipo de variáveis alguns deles são: '''string literals (words), numbers, sequences (lists), mapping (dictionaries), Booleans (true or false). Python tem tipagem dinâmica , então quando se faz a atribuição de valo a uma variável fica a cargo do interpretado determinar qual é o tipo do valor. Python só reclamará do uso de uma variável, somente se você estiver tentando usá-la sem antes ter atribuído algum valor. Um vez que python identificar qual o tipo de determinada variável ele irá indicar um erro se essa variável for usada em uma operação não apropriada para o tipo. Os traceback's é a forma de python alertar para um potencial erro na lógica do programa. O valor None tem o seu próprio tipo que é o NoneType. É o equivalente ao void do C. Carctere é o termo usado para descrever uma única letra, número ou ponto de marcação. Um valor criado usando marcas de citação '(quotetion marks) recebe o tipo '''str '(string). Uma coisa importante em python é que a string é '''imutável. Na prática pode se usar algumas funções para criar um nova string com o valor editado. Operações matemáticas Usando o opera / para dividir inteiros, diferentemente de C o resultado será em ponto flutuante. Caso o programador queira o resultado inteiro, desprezando a parte fracionária, ele deve usar o operador floor //, que retorna o maior inteiro menor que o resultado “real” da divisão. Para se obter o resto da divisão basta-se usar o operador de resto %, que realizará o calculo da seguinte forma: 13 % 5 = 13 – (5*(13//5)). Convertendo um número em outro int(x), float(x), str(x), converte a inteiro, ponto flutuante e string, respectivamente. É possível colocar e retirar números inteiros no formato octal (0o) e hexadecimal (0x). hex(x) e oct(x) mostra o inteiro x em representação hexadecimal e octacl, respectivamente. 'Comandos' Comparar resultado e mudar o curso de ação baseado nesses resultados formam instruções do tipo condicional. Em pseudo código esse tipo de instrução é escrita com as palavas if...then. Em python os operadores de comparação são <, >, <=, >=, , != . O resultado de toda comparação usando esses operadores resultam em True ou False. Uma expressão condicional consiste do conjunto operandos e operadores condicionais. Python pode gerar um erro se tipos ilógicos forem comparados. A função que retorna o comprimento de um string é a len(). Operadores booleanos tem uma precedência menor que todos os outros operadores matemáticos. A precedência entre eles está organizada da seguinte forma: not > and > or O sinal único de igualdade =''' tem a capacidade de desempacotar uma string. Ex.: c1, c2, c3 = “cat”; essa construção atribuirá cada um dos caracteres a respectiva variável na ordem que elas aparecerem. A quantidade de '''caracteres '''que serão desempacotados deve ser igual a quantidade de variáveis. Geralmente operadores que tem a mesma precedência são avaliados da esquerda para a direita, o que não acontece com operadores de comparação que são '''encadeados. Ex.: a + b + c = ((a +b) + c), já a < b < c = (a < b) and (b < c). Em python sentenças condicionais são criadas usando if, elif e eles. Comparações podem ser realizadas com qualquer coisa em pytohn, porque qualquer coisa pode ser avaliada em True ou False. Qualquer número é true. Sentenças condicionais 'são escritas na forma: if ''condicion: some actions elif condicion != true: some actions eles other actions Obser a identação, ela é muito importante. Designa que determinado grupo de instruções pertencem ao mesmo bloco. As sentenças que seguem o dois pontos são chamadas de '''suite. O elif '(equivale ao else-if de outras linguagens) só será avaliado se o '''if '''falhar. O '''else '(final) executará se nenhuma das condições anteriores suceder. Esse '''eles não necessita de um sentença condicional. A medida que a sua aplicação se torna mais complexa é preciso ter métodos formais para testar o projeto. Uma das formas de fazer isso é através de trace table (tabelas de rastreamento) A a função round() recebe dois argumentos, o número que se quer remover um excesso de dígitos e o número de casas decimais que se quer. Em pyton as duas principais formas de criar uma sentença de loop é através do while e do for. Pode-se usar break '''e '''continue nesses loops, da mesma forma que se usa em C. Existe no python uma sentença nula (que não faz nada). É o pass que funcion como o if(condicão); no C. No python não dá pra deixar apenas a linha vazia indicando que não há instruções. O for no pytohn é bem diferente do C. A sua sintaxe é for element in sequence: . Depois dos : vem o corpo do for que deve estar identado. Sequence pode ser tanto uma string, lista ou tupla. Element recebe um elemento (em sequencia) de sequence por iteração. 'Listas' Comparar resultado e mudar o curso de ação baseado nesses resultados formam instruções do tipo condicional. Em pseudo código esse tipo de instrução é escrita com as palavas if...then. Em python os operadores de comparação são <, >, <=, >=, , != . O resultado de toda comparação usando esses operadores resultam em True ou False. Uma expressão condicional consiste do conjunto operandos e operadores condicionais. Python pode gerar um erro se tipos ilógicos forem comparados. A função que retorna o comprimento de um string é a len(). Operadores booleanos tem uma precedência menor que todos os outros operadores matemáticos. A precedência entre eles está organizada da seguinte forma: not > and > or O sinal único de igualdade =''' tem a capacidade de desempacotar uma string. Ex.: c1, c2, c3 = “cat”; essa construção atribuirá cada um dos caracteres a respectiva variável na ordem que elas aparecerem. A quantidade de '''caracteres '''que serão desempacotados deve ser igual a quantidade de variáveis. Geralmente operadores que tem a mesma precedência são avaliados da esquerda para a direita, o que não acontece com operadores de comparação que são '''encadeados. Ex.: a + b + c = ((a +b) + c), já a < b < c = (a < b) and (b < c). Em python sentenças condicionais são criadas usando if, elif e eles. Comparações podem ser realizadas com qualquer coisa em pytohn, porque qualquer coisa pode ser avaliada em True ou False. Qualquer número é true. Sentenças condicionais 'são escritas na forma: if ''condicion: some actions elif condicion != true: some actions eles other actions Obser a identação, ela é muito importante. Designa que determinado grupo de instruções pertencem ao mesmo bloco. As sentenças que seguem o dois pontos são chamadas de '''suite. O elif '(equivale ao else-if de outras linguagens) só será avaliado se o '''if '''falhar. O '''else '(final) executará se nenhuma das condições anteriores suceder. Esse '''eles não necessita de um sentença condicional. A medida que a sua aplicação se torna mais complexa é preciso ter métodos formais para testar o projeto. Uma das formas de fazer isso é através de trace table (tabelas de rastreamento) A a função round() recebe dois argumentos, o número que se quer remover um excesso de dígitos e o número de casas decimais que se quer. Em pyton as duas principais formas de criar uma sentença de loop é através do while e do for. Pode-se usar break '''e '''continue nesses loops, da mesma forma que se usa em C. Existe no python uma sentença nula (que não faz nada). É o pass que funcion como o if(condicão); no C. No python não dá pra deixar apenas a linha vazia indicando que não há instruções. O for no pytohn é bem diferente do C. A sua sintaxe é for element in sequence: . Depois dos : vem o corpo do for que deve estar identado. Sequence pode ser tanto uma string, lista ou tupla. Element recebe um elemento (em sequencia) de sequence por iteração. 'Funções' Funções. Em scripts top-down não importa quão longo é o script ele sempre se inicia no topo da página e finaliza no “chão” da página. O problema dessa abordagem é que se eu quiser repetir a operação tenho que repetir o código. Para evitar isso, python (e várias outras linguagens) oferecem uma forma de quebrar o código em unidades funcionais, as funções. Com isso o código é segmentado e pedaços gerenciáveis. Um dos efeitos de se usar funções é o de que o trabalho interno delas podem ser alterados sem afetar as outras partes do programa. A primeira concelho no projeto de funções é: qual entra ela receberá e qual será o seu valor de retorno. Os parâmetros são o suprimento de dados a uma função e o valor de retorno é a saída (output). A definição de uma função inicia-se com a palavra-chave def seguida do nome da função com um conjunto opcional de parâmetros entre parênteses, terminando a linha com :, indicando com uma identação que as próximas sentenças formarão o corpo da função. def nome_func(par1, par2, par3): ' inst1' ' inst2 ' ' inst3' Em essência criar um função é dar um nome a cada peça de funcionalidade. Pode-se dizer o que uma função faz (descreve-la) usando docstring, que deve ser a primeira coisa do corpo da função. Lembre-se que deve vir compreendida entre “””(ignore esse esse intermediário)“””. Como em C, a palavra-chave return indica o que será retornado. Caso nada seja retonado, return não preceisa ser usado e o interpretador interpretará como return None (equivalente a null em C). A convenção de nomes para funções é a mesma para variáveis (letras minusculas podendo usar_), com a diferença que se deve usar palavrar que indicam a ação a ser realizada, i.e, verbos. Para fazer a função receber dados de um cliente, deve-se setar na definição da função variáveis para receber esses dados. É recomendado que estas variáveis não tenha os mesmos nomes que variáveis na “função cliente”. Essas variáveis são chamadas de parâmetros formais. Os argumentos passados para a função são chamados argumentos posicionais porque a atribuição aos parâmetro se dá na ordem em que eles foram declarados. Os parâmetros formais têm escopo local. A passagem se dá por valor. Pode-se setar valores default para os parâmetros da função fazendo: def nome_func (par1 = 1, par2 = 3) ' inst1' ' inst2' Dessa forma não há necessidade de passar argumentos na chamada. Pode-se também também chamar a função usando argumentos palavra-chave. Observe a seguinte chamada: nome_func(par1 = 4, par2 = 5) Dessa forma a ordem dos argumentos não importa mais. Pode-se passar um número desconhecido de argumentos para uma função desde que a definição dessa função esteja especifica da seguinte forma: def nome_func(*arg) O que acontece é que todos os argumentos passados se “unirão” em um tupla e serão atribuídos a arg. A seguinte construção também é válida: def nome_func(**arg) Na chamada a função passa-se argumentos palavra-chave e o parâmetro arg será um dicionário. Observe o exemplo: nome_func(var1 = 2, var2 = 3, var3 = 4) ' Será atribuído a arg = {'var1':2, 'var2':3, 'var3':4}' Esses dois conceitos podem ser usados juntos, mas o programador deve tomar cuidado em especifica os parâmetro posicionais antes dos argumentos palavra-chave. Pode-se usar na chamada a função os catadores de arumentos(*) O que acontecerá é uma expansão dos argumentos. Se a chamada for: nome_func(*args, **kwargs) e args = (1, 2, 3, 4) e kwargs = {a = 1, b = 10}. ' A chamada é equivalente a ' ' nome_func(1, 2, 3, 4, a = 1, b = 10)' Docstring par documentar funções É esperado que doctrings sigam determinada convenção. Na primeira linha deve ter um descrição curta (de uma linha ) sobre a função. A próxima linha deve estar em branco. Depois disso o corpo da docstring deve conter um descrição dos parâmetros, uma longa descrição da função, notas sobre o algoritmo usado e um exemplo de como usar a função que inclui detalhes sobre argumentos opcionais, argumentos-chaves e o valor de retorno. Deve-se incluir também informações sobre possíveis efeitos colaterais, exceções e restrições sobre onde a função pode ser chamada. Escopo. O código no programa principal que envia o código fonte espera o processamento (da função) e recebe o retorno é chamado de procedimento de chamada (calling procedure). Ele não precisa sabe o que se passa dentro da função (a mesma analogia de sempre). Quando qualquer programa está executando qualquer interpretador mantém um rastro (registro) de todos os nomes que são criados e usados no programa. Esses nomes são associados a uma tabela de símbolos '''e podem ser vistos como dicionário usando a função interna '''vars(). '''Todas as variáveis globais que estão na '''tabela de símbolos do programa principal podem ser vistas com a função interna gloals(). As variáveis que estão na tabela de símbolos do programa principal são conhecidas como globais. Qualquer variável que é criada em uma função é armazenada em um tabela de símbolos única a essa função. Essas variáveis são ditas locais. Podem ser acessadas dentro dessa função usando locals(). O corpo principal de um programa não pode acessar as variáveis setadas dentro de uma função. A função no entanto pode acessar as variáveis globais. Se em uma função um variável local tem o mesmo nome de uma variável global, suponhamos var. '''A função não conseguirá acessar a '''var global apenas var local. '''Variáveis com essa caracteristica são conhecidas como '''globais escurecidas (shadowed globals). Mesmo que seja possível acessas as variáveis globais dentro de uma função, é recomendado usar a sentença global para declarar essas variáveis. Ex.: var1 =1 ' def func()' ' global var1' ' var2 = 1 + var1' ' “se quiser modificar a variável global de dentro da função a sentença global é obrigatória”' ' var1 = 0 ' Manipulando lista e dicionário Parâmetros para uma função são passadas por valor (uma cópia, como em C). Mas no caso de objetos (diferentemente de tipos simples como strings e inteiros) se eles forem modificados dentro de uma função o resultado se reflete fora da função. A função pode ser usada para modificar dados mutáveis como dicionários e listas. Tecnicamente esse tipo de procedimento não é uma função pura nem precisa de argumento e valores de retorno. Para evitar efeitos laterais uma boa política geral é somente enviar dados imutáveis a funções e manter os procedimentos para tipos mutáveis separados. Se for mandado uma lista ou um dicionário para a função, o que se está fazendo é enviado um ponteiro para o objeto que representa o tipo mutável. Se está fazendo algo parecido como local_list = global_list. Refatorar é o processo de reescrever uma aplicação tornando-a mais fácil de manter ou mais eficiente sem alterar o comportamento original. Category:Orientação a objetos